package com.taotao.interceptor.config;

import com.taotao.interceptor.entity.BaseEntity;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.DefaultReflectorFactory;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.ReflectorFactory;
import org.apache.ibatis.reflection.factory.DefaultObjectFactory;
import org.apache.ibatis.reflection.factory.ObjectFactory;
import org.apache.ibatis.reflection.wrapper.DefaultObjectWrapperFactory;
import org.apache.ibatis.reflection.wrapper.ObjectWrapperFactory;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.PreparedStatement;
import java.util.Date;
import java.util.Properties;

@Intercepts({
        @Signature(type = ParameterHandler.class, method = "setParameters", args = PreparedStatement.class)
})
@Slf4j
@Component
public class ParamInterceptor implements Interceptor {


    private static final ObjectFactory DEFAULT_OBJECT_FACTORY = new DefaultObjectFactory();
    private static final ObjectWrapperFactory DEFAULT_OBJECT_WRAPPER_FACTORY = new DefaultObjectWrapperFactory();
    private static final ReflectorFactory REFLECTOR_FACTORY = new DefaultReflectorFactory();

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        log.info("<mayikt ParamInterceptor>");
        // 获取拦截器拦截的设置参数对象DefaultParameterHandler
        ParameterHandler parameterHandler = (ParameterHandler) invocation.getTarget();

        // 通过mybatis的反射来获取对应的值
        MetaObject metaResultSetHandler = MetaObject.forObject(parameterHandler, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY, REFLECTOR_FACTORY);
        MappedStatement mappedStatement = (MappedStatement) metaResultSetHandler.getValue("mappedStatement");
        Object parameterObject = metaResultSetHandler.getValue("parameterObject");

          if(parameterObject instanceof BaseEntity){
              //使用java反射机制赋值
              Class<?> aClass = parameterObject.getClass();
              aClass.getSuperclass().getDeclaredField("createDatetime");
          }
        //sql类型
        SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
        // 回写parameterObject对象
        metaResultSetHandler.setValue("parameterObject", updateInsertParam(sqlCommandType, parameterObject));
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {

    }

    private Object updateInsertParam(SqlCommandType sqlCommandType, Object parameterObject) throws NoSuchFieldException, IllegalAccessException {
        Class<?> aClass = parameterObject.getClass();
        switch (sqlCommandType) {
            case INSERT:
                // 使用反射获取到createDatetime修改时间为当前系统时间
                Field createDatetime = aClass.getSuperclass().getDeclaredField("createDatetime");
                createDatetime.setAccessible(true);
                createDatetime.set(parameterObject, new Date());
                break;
            case UPDATE:
                //updateDatetime字段 修改时间为当前系统时间
                Field updateDatetime = aClass.getSuperclass().getDeclaredField("updateDatetime");
                updateDatetime.setAccessible(true);
                updateDatetime.set(parameterObject, new Date());
                break;
        }
        return parameterObject;
    }
}